home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / os2 / gclient.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-18  |  70.9 KB  |  2,133 lines

  1. #ifdef INCRC ô§T"óXr RCSid[]="$Id: gclient.c,v 1.7 1998/12/17 22:10:28 lhecking Exp $" ;
  2. #endif
  3.  
  4. /****************************************************************************
  5.  
  6.     PROGRAM: Gnupmdrv
  7.     
  8.     MODULE:  gclient.c
  9.         
  10.     This file contains the client window procedures for Gnupmdrv
  11.     
  12. ****************************************************************************/
  13.  
  14. /* PM driver for GNUPLOT */
  15.  
  16. /*[
  17.  * Copyright 1992, 1993, 1998   Roger Fearick
  18.  *
  19.  * Permission to use, copy, and distribute this software and its
  20.  * documentation for any purpose with or without fee is hereby granted,
  21.  * provided that the above copyright notice appear in all copies and
  22.  * that both that copyright notice and this permission notice appear
  23.  * in supporting documentation.
  24.  *
  25.  * Permission to modify the software is granted, but not the right to
  26.  * distribute the complete modified source code.  Modifications are to
  27.  * be distributed as patches to the released version.  Permission to
  28.  * distribute binaries produced by compiling modified sources is granted,
  29.  * provided you
  30.  *   1. distribute the corresponding source modifications from the
  31.  *    released version in the form of a patch file along with the binaries,
  32.  *   2. add special version identification to distinguish your version
  33.  *    in addition to the base release version number,
  34.  *   3. provide your name and address as the primary contact for the
  35.  *    support of your modified version, and
  36.  *   4. retain our contact information in regard to use of the base
  37.  *    software.
  38.  * Permission to distribute the released version of the source code along
  39.  * with corresponding source modifications in the form of a patch file is
  40.  * granted with same provisions 2 through 4 for binary distributions.
  41.  *
  42.  * This software is provided "as is" without express or implied warranty
  43.  * to the extent permitted by applicable law.
  44. ]*/
  45.  
  46. /*
  47.  * AUTHOR
  48.  * 
  49.  *   Gnuplot driver for OS/2:  Roger Fearick
  50.  * 
  51.  * Send your comments or suggestions to 
  52.  *  info-gnuplot@dartmouth.edu.
  53.  * This is a mailing list; to join it send a note to 
  54.  *  majordomo@dartmouth.edu.  
  55.  * Send bug reports to
  56.  *  bug-gnuplot@dartmouth.edu.
  57. **/
  58.  
  59. #define INCL_PM
  60. #define INCL_WIN
  61. #define INCL_SPL
  62. #define INCL_SPLDOSPRINT
  63. #define INCL_WINSTDFONT
  64. #define INCL_DOSMEMMGR
  65. #define INCL_DOSPROCESS
  66. #define INCL_DOSERRORS
  67. #define INCL_DOSFILEMGR
  68. #define INCL_DOSNMPIPES
  69. #define INCL_DOSSESMGR
  70. #define INCL_DOSSEMAPHORES
  71. #define INCL_DOSMISC
  72. #define INCL_DOSQUEUES
  73. #define INCL_WINSWITCHLIST
  74. #include <os2.h>
  75. #include <string.h>
  76. #include <stdio.h>
  77. #include <io.h>
  78. #include <fcntl.h>
  79. #include <math.h>
  80. #include <stdlib.h>
  81. #include <unistd.h>
  82. #include <process.h>
  83. #include <signal.h>
  84. #include "gnupmdrv.h"
  85.  
  86. /*==== g l o b a l    d a t a ================================================*/
  87.  
  88. extern char szIPCName[] ;       /* name used in IPC with gnuplot */
  89. extern char szIniFile[256] ;    /* full path of ini file */
  90. extern int  bServer ;
  91. extern int  bPersist ;
  92. extern int  bEnhanced ;
  93.  
  94. /*==== l o c a l    d a t a ==================================================*/
  95.  
  96. static long lLineTypes[7] = { LINETYPE_SOLID,
  97.                               LINETYPE_SHORTDASH,
  98.                               LINETYPE_DOT,
  99.                               LINETYPE_DASHDOT,
  100.                               LINETYPE_LONGDASH,
  101.                               LINETYPE_DOUBLEDOT,
  102.                               LINETYPE_DASHDOUBLEDOT } ;
  103. static long lCols[16] =     { CLR_BLACK,
  104.                               CLR_DARKGRAY,
  105.                               CLR_BLUE,
  106.                               CLR_RED,
  107.                               CLR_GREEN,
  108.                               CLR_CYAN,
  109.                               CLR_PINK,
  110.                               CLR_YELLOW,
  111.                               CLR_DARKBLUE,
  112.                               CLR_DARKRED,
  113.                               CLR_DARKGREEN,
  114.                               CLR_DARKCYAN,
  115.                               CLR_DARKPINK,
  116.                               CLR_BROWN,
  117.                               CLR_PALEGRAY,
  118.                               CLR_WHITE } ;
  119.  
  120. static LONG alColourTable[ 16 ] ;
  121.  
  122. #define   GNUBUF    1024        /* buffer for gnuplot commands */
  123. #define   PIPEBUF   4096        /* size of pipe buffers */
  124. #define   CMDALLOC  4096        /* command buffer allocation increment (ints) */
  125. #define   ENVSIZE   2048        /* size of environment */ 
  126.  
  127. #define   PAUSE_DLG 1           /* pause handled in dialog box */
  128. #define   PAUSE_BTN 2           /* pause handled by menu item */
  129. #define   PAUSE_GNU 3           /* pause handled by Gnuplot */
  130.  
  131. #define   DEFLW     50
  132.  
  133. static ULONG    ppidGnu=0L ;      /* gnuplot pid */
  134. static HPS      hpsScreen ;     /* screen pres. space */
  135. static int      iSeg = 1 ;
  136.  
  137. static HSWITCH hSwitch = 0 ;    /* switching between windows */
  138. static SWCNTRL swGnu ;
  139.  
  140. static BOOL     bLineTypes = FALSE ;    // true if use dashed linetypes
  141. BOOL     bWideLines ;
  142. static BOOL     bColours = TRUE ;
  143. static BOOL     bShellPos = FALSE ;
  144. static BOOL     bPlotPos = FALSE ;
  145. static BOOL     bPopFront = TRUE ;
  146. static BOOL     bNewFont = FALSE ;
  147. static BOOL     bHorz = TRUE ;
  148.  
  149. static ULONG    ulPlotPos[4] ;
  150. static ULONG    ulShellPos[4] ;
  151. static PAUSEDATA pausedata = {sizeof(PAUSEDATA), NULL, NULL} ;
  152. static char     szFontNameSize[FONTBUF] ;
  153. static PRQINFO3 infPrinter = { "" } ;
  154. static QPRINT   qPrintData = { sizeof(QPRINT), 0.0, 0.0, 1.0, 1.0, 0, 
  155.                                "", "", &infPrinter, 0, NULL } ;
  156. //static HEV      semStartSeq ;   /* semaphore to start things in right sequence */
  157. static HEV      semPause ;
  158. static HMTX     semHpsAccess ;
  159. static ULONG    ulPauseReply = 1 ;
  160. static ULONG    ulPauseMode  = PAUSE_DLG ;
  161.  
  162. static HWND     hSysMenu ;
  163.             /* stuff for screen-draw thread control */
  164.             
  165. static BOOL     bExist ; 
  166. //static HEV      semDrawDone ;
  167.  
  168.             /* thread control */
  169.  
  170. static TID     tidDraw, tidSpawn ;
  171.  
  172.             /* font data */
  173.  
  174. static int lSupOffset = 0 ;
  175. static int lSubOffset = 0 ;
  176. static int lBaseSupOffset = 0 ;
  177. static int lBaseSubOffset = 0 ;
  178. static int lCharWidth = 217 ;
  179. static int lCharHeight = 465 ; 
  180.  
  181.  
  182. /*==== f u n c t i o n s =====================================================*/
  183.  
  184. int             DoPrint( HWND ) ;
  185. HBITMAP         CopyToBitmap( HPS ) ; 
  186. HMF             CopyToMetaFile( HPS ) ; 
  187. MRESULT         WmClientCmdProc( HWND , ULONG, MPARAM, MPARAM ) ; 
  188. void            ChangeCheck( HWND, USHORT, USHORT ) ;
  189. BOOL            QueryIni( HAB ) ;
  190. static void     SaveIni( HWND ) ;
  191. static void     ThreadDraw( void* ) ;
  192. static void     DoPaint( HWND, HPS ) ;
  193. static void     Display( HPS ) ;
  194. void            SelectFont( HPS, char * );
  195. void            SwapFont( HPS, char * );
  196. static void     CopyToClipBrd( HWND ) ; 
  197. static void     ReadGnu( void* ) ;
  198. static void     EditLineTypes( HWND, HPS, BOOL ) ;
  199. static void     EditCharCell( HPS, SIZEF* ) ;
  200. static HPS      InitScreenPS( void ) ;
  201. static int      BufRead( HFILE, void*, int, PULONG ) ;
  202. int             GetNewFont( HWND, HPS ) ;
  203. void            SigHandler( int ) ;
  204. void            FontExpand( char * ) ;
  205. static char    *ParseText(HPS, char *, BOOL, char *,
  206.                        int, int, BOOL, BOOL ) ;
  207. static void     CharStringAt(HPS, int, int, int, char *) ;
  208. static int      QueryTextBox( HPS, int, char * ) ; 
  209. static void      LMove( HPS hps, POINTL *p ) ;
  210. static void      LLine( HPS hps, POINTL *p ) ;
  211. static void      LType( int iType ) ;
  212.  
  213. /*==== c o d e ===============================================================*/
  214.  
  215. MRESULT EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
  216. /*
  217. **  Window proc for main window
  218. **  -- passes most stuff to active child window via WmClientCmdProc
  219. **  -- passes DDE messages to DDEProc
  220. */
  221. {
  222.     static BOOL    bSw = FALSE ;
  223.     static BOOL    bFirst = TRUE ; 
  224.     static RECTL   rectlPaint = { 0, 0, 0, 0 } ;
  225.     static int     iPaintCount = 0 ;
  226.     static int     firstcall = 1 ;
  227.     
  228.     switch (message) {
  229.  
  230.         case WM_CREATE:
  231.             {
  232.             HDC     hdcScreen ;
  233.             SIZEL   sizlPage ;
  234.                 // set initial values
  235.             ChangeCheck( hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0 ) ;
  236.             ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
  237.             ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
  238.             ChangeCheck( hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0 ) ;
  239.                 // disable close from system menu (close only from gnuplot)
  240.             hApp = WinQueryWindow( hWnd, QW_PARENT ) ; /* temporary assignment.. */
  241.             hSysMenu = WinWindowFromID( hApp, FID_SYSMENU ) ;
  242.                 // setup semaphores
  243. //            DosCreateEventSem( NULL, &semDrawDone, 0L, 0L ) ;
  244. //            DosCreateEventSem( NULL, &semStartSeq, 0L, 0L ) ;
  245.             DosCreateEventSem( NULL, &semPause, 0L, 0L ) ;
  246.             DosCreateMutexSem( NULL, &semHpsAccess, 0L, 1L ) ;
  247.             bExist = TRUE ;
  248.                 // create a dc and hps to draw on the screen
  249.             hdcScreen = WinOpenWindowDC( hWnd ) ;
  250.             sizlPage.cx = 0 ; sizlPage.cy = 0 ;
  251.             sizlPage.cx = 19500 ; sizlPage.cy = 12500 ;
  252.             hpsScreen = GpiCreatePS( hab, hdcScreen, &sizlPage,
  253.                            PU_HIMETRIC|GPIT_NORMAL|GPIA_ASSOC) ;
  254.                 // spawn server for GNUPLOT ...
  255.             tidSpawn = _beginthread( ReadGnu, NULL, 32768, NULL ) ;
  256.             }
  257.             break ;
  258.             
  259.         case WM_GPSTART:
  260.  
  261.                 // get details of command-line window
  262.             hSwitch = WinQuerySwitchHandle( 0, ppidGnu ) ;
  263.             WinQuerySwitchEntry( hSwitch, &swGnu ) ;
  264.             if( firstcall ) {
  265.                 // set size of this window
  266.             WinSetWindowPos( WinQueryWindow( hWnd, QW_PARENT ), 
  267.                              bPopFront?HWND_TOP:swGnu.hwnd,
  268.                              ulShellPos[0],
  269.                              ulShellPos[1],
  270.                              ulShellPos[2],
  271.                              ulShellPos[3], 
  272.                              bShellPos?(bPopFront?SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ACTIVATE
  273.                                                  :SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ZORDER)
  274.                                       :(bPopFront?SWP_SHOW|SWP_ACTIVATE:SWP_SHOW|SWP_ZORDER) ) ;
  275.             signal( SIGTERM, SigHandler ) ;
  276.                 firstcall = 0 ;
  277.                 }
  278.             if( !bPopFront ) WinSwitchToProgram( hSwitch ) ;
  279. //            DosPostEventSem( semDrawDone ) ;
  280.             DosReleaseMutexSem( semHpsAccess ) ;
  281.             return 0 ;
  282.             
  283.         case WM_COMMAND:
  284.  
  285.             return WmClientCmdProc( hWnd , message , mp1 , mp2 ) ;
  286.  
  287.         case WM_CHAR:    
  288.                     /* If the user types a command in the driver window,
  289.                        we route it to the gnuplot window and switch that
  290.                        to the front. Doesn't work for full-screen
  291.                        sessions, though (but does switch).  */
  292.             {
  293.             USHORT  usFlag ;
  294.             usFlag = SHORT1FROMMP( mp1 ) ;
  295.             if(  !(usFlag & (KC_KEYUP|KC_ALT|KC_CTRL)) ) {
  296.                 USHORT uc = SHORT1FROMMP( mp2 ) ;
  297.                     HWND hw = WinQueryWindow( swGnu.hwnd, QW_BOTTOM ) ;
  298.                     WinSetFocus( HWND_DESKTOP, hw ) ; 
  299.                 WinSendMsg( hw, message, 
  300.                             MPFROM2SHORT((USHORT)(KC_SCANCODE), 1), 
  301.                             MPFROMSHORT(uc) ) ;
  302.                     WinSwitchToProgram( hSwitch ) ;
  303.                     }
  304.             }
  305.             break ;        
  306.  
  307.         case WM_DESTROY:
  308.  
  309.             if( WinSendMsg( hWnd, WM_USER_PRINT_QBUSY, 0L, 0L ) != 0L ) {
  310.                 WinMessageBox( HWND_DESKTOP,
  311.                                hWnd, 
  312.                                "Still printing - not closed",
  313.                                APP_NAME,
  314.                                0,
  315.                                MB_OK | MB_ICONEXCLAMATION ) ;
  316.                 return 0L ;
  317.                 }
  318.               return (WinDefWindowProc(hWnd, message, mp1, mp2));
  319.  
  320.         case WM_PAINT:
  321.             {
  322.             ULONG ulCount ;
  323.             PID pid; TID tid;
  324.             HPS hps_tmp;
  325.             RECTL rectl_tmp;
  326.               DosQueryMutexSem( semHpsAccess, &pid, &tid, &ulCount ) ;
  327.             if (( ulCount > 0 ) && (tid != tidDraw)) {
  328.                 /* simple repaint while building plot or metafile */
  329.                 /* use temporary PS                   */
  330.               hps_tmp = WinBeginPaint(hWnd,0,&rectl_tmp );
  331.               WinFillRect(hps_tmp,&rectl_tmp,CLR_BACKGROUND);
  332.               WinEndPaint(hps_tmp);
  333.                 /* add dirty rectangle to saved rectangle     */
  334.                 /* to be repainted when PS is available again */
  335.               WinUnionRect(hab,&rectlPaint,&rectl_tmp,&rectlPaint);
  336.                 iPaintCount ++ ;
  337.                 break ;
  338.                 } 
  339.             WinInvalidateRect( hWnd, &rectlPaint, TRUE ) ;
  340.             DoPaint( hWnd, hpsScreen ) ;
  341.             WinSetRectEmpty( hab, &rectlPaint ) ;
  342.             }
  343.             break ;     
  344.  
  345.         case WM_SIZE :
  346.             
  347.             {
  348.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  349.             }
  350.             break ;
  351.  
  352.         case WM_PRESPARAMCHANGED:
  353.             {        
  354.             char *pp ;
  355.             ULONG ulID ;
  356.             pp = malloc(FONTBUF) ;
  357.             if( WinQueryPresParam( hWnd, 
  358.                                    PP_FONTNAMESIZE, 
  359.                                    0, 
  360.                                    &ulID, 
  361.                                    FONTBUF, 
  362.                                    pp, 
  363.                                    QPF_NOINHERIT ) != 0L ) {
  364.                 strcpy( szFontNameSize, pp ) ;
  365.                 bNewFont = TRUE ;
  366.                 WinInvalidateRect( hWnd, NULL, TRUE ) ;
  367.                 }
  368.             free(pp) ;
  369.             } 
  370.             break ;
  371.             
  372.         case WM_USER_PRINT_BEGIN:
  373.         case WM_USER_PRINT_OK :
  374.         case WM_USER_DEV_ERROR :
  375.         case WM_USER_PRINT_ERROR :
  376.         case WM_USER_PRINT_QBUSY :
  377.  
  378.             return( PrintCmdProc( hWnd, message, mp1, mp2 ) ) ;
  379.  
  380.         case WM_GNUPLOT:
  381.                 // display the plot         
  382.             if( bPopFront )
  383.                 WinSetWindowPos( hwndFrame, HWND_TOP, 0,0,0,0, SWP_ACTIVATE|SWP_ZORDER ) ;
  384.             if( iPaintCount > 0 ) { /* if outstanding paint messages, repaint */
  385.                 WinInvalidateRect( hWnd, &rectlPaint, TRUE ) ;
  386.                 iPaintCount = 0 ;
  387.                 }
  388.             return 0L ;
  389.  
  390.         case WM_PAUSEPLOT:
  391.                 /* put pause message on screen, or enable 'continue' button */
  392.             if( ulPauseMode == PAUSE_DLG ) {
  393.                 pausedata.pszMessage = (char*)mp1 ;
  394.                 WinLoadDlg( HWND_DESKTOP,
  395.                             hWnd,
  396.                             (PFNWP)PauseMsgDlgProc,
  397.                             0L,
  398.                             IDD_PAUSEBOX,
  399.                             &pausedata ) ; 
  400.                 }
  401.             else { 
  402.                 WinEnableMenuItem( WinWindowFromID( 
  403.                                    WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
  404.                                    IDM_CONTINUE,
  405.                                    TRUE ) ;            
  406.                 }
  407.             return 0L ;
  408.  
  409.         case WM_PAUSEEND:
  410.             /* resume plotting */
  411.             ulPauseReply = (ULONG) mp1 ;
  412.             DosPostEventSem( semPause ) ;
  413.             return 0L ;
  414.     
  415.     default:         /* Passes it on if unproccessed    */
  416.         return (WinDefWindowProc(hWnd, message, mp1, mp2));
  417.     }
  418.     return (NULL);
  419. }
  420.  
  421. MRESULT WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
  422. /*
  423. **   Handle client window command (menu) messages
  424. */
  425.     {
  426.     extern HWND hApp ;
  427.     static ulPauseItem = IDM_PAUSEDLG ;
  428.  
  429.     switch( (USHORT) SHORT1FROMMP( mp1 ) ) {
  430.                 
  431.         case IDM_ABOUT :    /* show the 'About' box */
  432.              
  433.             WinDlgBox( HWND_DESKTOP,
  434.                        hWnd , 
  435.                        (PFNWP)About ,
  436.                        0L,
  437.                        ID_ABOUT, 
  438.                        NULL ) ;
  439.             break ;
  440.  
  441.  
  442.         case IDM_GPLOTINF:  /* view gnuplot.inf */
  443.             {
  444.             char path[256] ;
  445.             char *p ;
  446.             strcpy( path, "start view " ) ;
  447.             if( (p=getenv("GNUPLOT")) != NULL ) {
  448.                 strcat( path, p ) ;
  449.                 strcat( path, "/" ) ;
  450.                 }    
  451.             strcat( path, "gnuplot" ) ;
  452.             system( path ) ;
  453.             }
  454.             break ;
  455.             
  456.         case IDM_PRINT :    /* print plot */
  457.  
  458.             if( SetupPrinter( hWnd, &qPrintData ) ) {
  459.                             WinPostMsg( hWnd, 
  460.                             WM_USER_PRINT_BEGIN, 
  461.                             (MPARAM) &qPrintData, 
  462.                             (MPARAM) hpsScreen ) ; 
  463.                             }
  464.             break ;
  465.  
  466.         case IDM_PRINTSETUP :    /* select printer */
  467.  
  468.             WinDlgBox( HWND_DESKTOP,
  469.                        hWnd ,
  470.                        (PFNWP)QPrintersDlgProc,
  471.                        0L,
  472.                        IDD_QUERYPRINT, 
  473.                        qPrintData.szPrinterName ) ;
  474.             break ;
  475.  
  476.         case IDM_LINES_THICK:
  477.                 // change line setting
  478.             bWideLines = !bWideLines ;
  479.             ChangeCheck( hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0 ) ;
  480.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  481.             break ;
  482.  
  483.         case IDM_LINES_SOLID:
  484.                 // change line setting
  485.             bLineTypes = !bLineTypes ;
  486.             ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
  487.             EditLineTypes( hWnd, hpsScreen, bLineTypes ) ;
  488.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  489.             break ;
  490.  
  491.         case IDM_COLOURS:
  492.                 // change colour setting
  493.             bColours = !bColours ;        
  494.             ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
  495.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  496.             break ;
  497.  
  498.         case IDM_FRONT:
  499.                 /* toggle z-order forcing */
  500.             bPopFront = !bPopFront ;        
  501.             ChangeCheck( hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0 ) ;
  502.             break ;
  503.  
  504.         case IDM_FONTS:
  505.         
  506.             if( GetNewFont( hWnd, hpsScreen ) ) {
  507.                 bNewFont = TRUE ;
  508.                 WinInvalidateRect( hWnd, NULL, TRUE ) ;
  509.                 }
  510.             break ;
  511.             
  512.         case IDM_SAVE :
  513.             SaveIni( hWnd ) ;
  514.             break ;
  515.             
  516.         case IDM_COPY :         /* copy to clipboard */
  517.             if( WinOpenClipbrd( hab ) ) {
  518.                 CopyToClipBrd( hWnd ) ; 
  519.                 }
  520.             else {
  521.                 WinMessageBox( HWND_DESKTOP,
  522.                                hWnd, 
  523.                                "Can't open clipboard",
  524.                                APP_NAME,
  525.                                0,
  526.                                MB_OK | MB_ICONEXCLAMATION ) ;
  527.                 }
  528.             break ;
  529.  
  530.         case IDM_CLEARCLIP :         /* clear clipboard */
  531.             if( WinOpenClipbrd( hab ) ) {
  532.                 WinEmptyClipbrd( hab ) ;
  533.                 WinCloseClipbrd( hab ) ;
  534.                 }
  535.             else {
  536.                 WinMessageBox( HWND_DESKTOP,
  537.                                hWnd, 
  538.                                "Can't open clipboard",
  539.                                APP_NAME,
  540.                                0,
  541.                                MB_OK | MB_ICONEXCLAMATION ) ;
  542.                 }
  543.             break ;
  544.  
  545.         case IDM_COMMAND:       /* go back to GNUPLOT command window */
  546.             WinSwitchToProgram( hSwitch ) ;
  547.             break ;
  548.  
  549.         case IDM_CONTINUE:
  550.             WinPostMsg( hWnd, WM_PAUSEEND, (MPARAM)1L, (MPARAM)0L ) ; 
  551.             WinEnableMenuItem( WinWindowFromID( 
  552.                                WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
  553.                                IDM_CONTINUE,
  554.                                FALSE ) ;            
  555.             break ;
  556.             
  557.         case IDM_PAUSEGNU:  /* gnuplot handles pause */
  558.             ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEGNU ) ;
  559.             ulPauseItem = IDM_PAUSEGNU ;
  560.             ulPauseMode = PAUSE_GNU ;
  561.             break ;
  562.             
  563.         case IDM_PAUSEDLG:  /* pause message in dlg box */
  564.             ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEDLG ) ;
  565.             ulPauseItem = IDM_PAUSEDLG ;
  566.             ulPauseMode = PAUSE_DLG ;
  567.             break ;
  568.             
  569.         case IDM_PAUSEBTN:  /* pause uses menu button, no message */
  570.             ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEBTN ) ;
  571.             ulPauseItem = IDM_PAUSEBTN ;
  572.             ulPauseMode = PAUSE_BTN ;
  573.             break ;
  574.           
  575.         case IDM_HELPFORHELP:
  576.             WinSendMsg(WinQueryHelpInstance(hWnd),
  577.                        HM_DISPLAY_HELP, 0L, 0L ) ;
  578.             return 0L ;
  579.  
  580.         case IDM_EXTENDEDHELP:
  581.             WinSendMsg(WinQueryHelpInstance(hWnd),
  582.                         HM_EXT_HELP, 0L, 0L);
  583.             return 0L ;
  584.  
  585.         case IDM_KEYSHELP:
  586.             WinSendMsg(WinQueryHelpInstance(hWnd),
  587.                        HM_KEYS_HELP, 0L, 0L);
  588.             return 0L ;
  589.  
  590.         case IDM_HELPINDEX:
  591.             WinSendMsg(WinQueryHelpInstance(hWnd),
  592.                        HM_HELP_INDEX, 0L, 0L);
  593.             return 0L ;
  594.  
  595.         default : 
  596.     
  597.             return WinDefWindowProc( hWnd, message, mp1, mp2 ) ;
  598.  
  599.         }  
  600.     return( NULL ) ;
  601.     }                      
  602.  
  603. void ChangeCheck( HWND hWnd , USHORT wItem1 , USHORT wItem2 )
  604. /*
  605. **  Utility function:
  606. **
  607. **  move check mark from menu item 1 to item 2
  608. */
  609.     {
  610.     HWND hMenu ;
  611.  
  612.     hMenu = WinWindowFromID( WinQueryWindow( hWnd, QW_PARENT ), 
  613.                              FID_MENU ) ;            
  614.     if( wItem1 != 0 )
  615.         WinSendMsg( hMenu,
  616.                     MM_SETITEMATTR,
  617.                     MPFROM2SHORT( wItem1, TRUE ),
  618.                     MPFROM2SHORT( MIA_CHECKED, 0 ) ) ;
  619.     if( wItem2 != 0 )
  620.         WinSendMsg( hMenu,
  621.                     MM_SETITEMATTR,
  622.                     MPFROM2SHORT( wItem2, TRUE ),
  623.                     MPFROM2SHORT( MIA_CHECKED, MIA_CHECKED ) ) ;
  624.     }       
  625.  
  626. static void CopyToClipBrd( HWND hWnd ) 
  627. /*
  628. **  Copy window to clipboard as bitmap.
  629. */
  630.     {
  631.     HAB hab ;
  632.     HBITMAP hbm ;
  633.     HMF     hmf ;
  634.  
  635.     hab = WinQueryAnchorBlock( hWnd ) ;
  636.     WinEmptyClipbrd( hab ) ;
  637.     hbm = CopyToBitmap( hpsScreen ) ; 
  638.     WinSetClipbrdData( hab, (ULONG) hbm, CF_BITMAP, CFI_HANDLE) ;
  639.     hmf = CopyToMetaFile( hpsScreen ) ; 
  640.     WinSetClipbrdData( hab, (ULONG) hmf, CF_METAFILE, CFI_HANDLE) ;
  641.     WinCloseClipbrd( hab ) ;
  642.     }
  643.  
  644. HBITMAP CopyToBitmap( HPS hps ) 
  645. /*
  646. **  Copy ps to a bitmap.
  647. */
  648.     {
  649.     HPS     hpsMem ;
  650.     HWND    hwnd ;
  651.     HAB     hab ;
  652.     PSZ     psz[4] = {NULL,"Display",NULL,NULL} ;
  653.     HDC     hdcMem, hdcScr ;
  654.     SIZEL   sizel ;
  655.     BITMAPINFOHEADER2 bmp ;
  656.     PBITMAPINFO2 pbmi ;
  657.     HBITMAP hbm ;
  658.     BYTE    abBmp[80] ;
  659.     LONG    alData[2] ;
  660.     RECTL   rectl ;
  661.     POINTL  aptl[6] ;
  662.     HMF     hmf ;
  663.  
  664.     hdcScr = GpiQueryDevice( hps ) ;
  665.     hwnd = WinWindowFromDC( hdcScr ) ;
  666.     hab = WinQueryAnchorBlock( hwnd ) ;
  667.     hdcMem = DevOpenDC( hab, 
  668.                         OD_MEMORY, 
  669.                         "*", 
  670.                         4L, 
  671.                         (PDEVOPENDATA) psz, 
  672.                         hdcScr ) ;
  673.     sizel.cx = 0/*GNUPAGE*/ ; sizel.cy = 0/*GNUPAGE*/ ;
  674.     hpsMem = GpiCreatePS( hab, hdcMem, &sizel, PU_PELS|GPIA_ASSOC|GPIT_MICRO ) ;
  675.     GpiQueryDeviceBitmapFormats( hpsMem, 2L, alData ) ;
  676.     WinQueryWindowRect( hwnd, &rectl ) ;
  677.     memset( &bmp, 0, sizeof(bmp) ) ;
  678.     bmp.cbFix = (ULONG) sizeof( bmp ) ;
  679.     bmp.cx = (SHORT) (rectl.xRight-rectl.xLeft) ;
  680.     bmp.cy = (SHORT) (rectl.yTop-rectl.yBottom) ;
  681.     bmp.cPlanes = alData[0] ;
  682.     bmp.cBitCount = alData[1] ;
  683.     hbm = GpiCreateBitmap( hpsMem, &bmp, 0, NULL, NULL ) ;
  684.     GpiSetBitmap( hpsMem, hbm ) ;
  685.     aptl[0].x = 0 ; aptl[0].y = 0 ;
  686.     aptl[1].x = (LONG)bmp.cx ; aptl[1].y = (LONG)bmp.cy ;
  687.     aptl[2].x = 0 ; aptl[2].y = 0 ;
  688.     GpiBitBlt( hpsMem, hps, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE ) ;
  689.     GpiDestroyPS( hpsMem ) ;
  690.     DevCloseDC( hdcMem ) ;
  691.     return hbm ;
  692.     }
  693.  
  694. HMF CopyToMetaFile( HPS hps ) 
  695. /*
  696. **  Copy ps to a mteafile.
  697. */
  698.     {
  699.     HDC hdcMF, hdcOld ;
  700.     HAB hab ;
  701.     HWND hwnd ;    
  702.     PSZ psz[4] = {NULL,"Display",NULL,NULL} ;
  703.     HMF hmf ;
  704.     hdcOld = GpiQueryDevice( hps ) ;
  705.     hwnd = WinWindowFromDC( hdcOld ) ;
  706.     hab = WinQueryAnchorBlock( hwnd ) ;
  707.     hdcMF = DevOpenDC( hab, OD_METAFILE, "*", 4L, psz, hdcOld ) ;
  708.     DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
  709.     GpiSetDrawingMode( hps, DM_DRAW ) ; 
  710.     GpiAssociate( hps, 0 ) ; 
  711.     GpiAssociate( hps, hdcMF ) ;
  712.     ScalePS( hps ) ;    
  713.     GpiDrawChain( hps ) ;
  714.     GpiAssociate( hps, 0 ) ; 
  715.     GpiAssociate( hps, hdcOld ) ; 
  716.     DosReleaseMutexSem( semHpsAccess ) ;
  717.     hmf = DevCloseDC( hdcMF ) ;
  718.     return hmf ;
  719.     }
  720.  
  721. BOOL QueryIni( HAB hab )
  722. /*
  723. ** Query INI file
  724. */
  725.     {
  726.     BOOL         bPos, bData, bSwp  ;
  727.     ULONG        ulOpts[5] ;
  728.     HINI         hini ;
  729.     ULONG        ulCB ;
  730.     char         *p ;
  731.     static SWP   pauseswp ;
  732.     
  733.             // read gnuplot ini file
  734.  
  735.     hini = PrfOpenProfile( hab, szIniFile ) ;
  736.     ulCB = sizeof( ulShellPos ) ;
  737.     bPos = PrfQueryProfileData( hini, APP_NAME, INISHELLPOS, &ulShellPos, &ulCB ) ;
  738.     ulCB = sizeof( SWP ) ;
  739.     bSwp = PrfQueryProfileData( hini, APP_NAME, INIPAUSEPOS, &pauseswp, &ulCB ) ;
  740.     if( bSwp ) pausedata.pswp = &pauseswp ;
  741.     ulCB = sizeof( ulOpts ) ;
  742.     bData = PrfQueryProfileData( hini, APP_NAME, INIOPTS, &ulOpts, &ulCB ) ;
  743.     if( bData ) {
  744.         bLineTypes = (BOOL)ulOpts[0] ;
  745.         bWideLines = (BOOL)ulOpts[1] ;
  746.         bColours = (BOOL)ulOpts[2] ;
  747.         ulPauseMode = ulOpts[3] ;
  748.         bPopFront = (BOOL)ulOpts[4] ;
  749.         }
  750.     else {
  751.         bLineTypes = FALSE ;  /* default values */
  752.      /*   bWideLines = FALSE ; */
  753.         bColours = TRUE ;
  754.         bPopFront = TRUE ;
  755.         ulPauseMode = 1 ;
  756.         }
  757.     ulCB = 4*sizeof(float) ;
  758.     PrfQueryProfileData( hini, APP_NAME, INIFRAC, &qPrintData.xsize, &ulCB ) ;
  759.     if( PrfQueryProfileSize( hini, APP_NAME, INIPRDRIV, &ulCB ) ) {
  760.         PDRIVDATA pdriv = (PDRIVDATA) malloc( ulCB ) ;
  761.         if( pdriv != NULL ) {
  762.             PrfQueryProfileData( hini, APP_NAME, INIPRDRIV, pdriv, &ulCB ) ;
  763.             qPrintData.pdriv = pdriv ;
  764.             qPrintData.cbpdriv = ulCB ;
  765.             }
  766.         }
  767.     PrfQueryProfileString( hini, APP_NAME, INIPRPR, "", 
  768.                            qPrintData.szPrinterName,
  769.                            (long) sizeof qPrintData.szPrinterName ) ;
  770.     PrfQueryProfileString( hini, APP_NAME, INIFONT, INITIAL_FONT, 
  771.                              szFontNameSize, FONTBUF ) ;
  772.     ulCB = sizeof( ulOpts ) ;
  773.     bData = PrfQueryProfileData( hini, APP_NAME, INICHAR, &ulOpts, &ulCB ) ;
  774.     if( bData ) {
  775.         lCharWidth = ulOpts[0] ;
  776.         lCharHeight = ulOpts[1] ;
  777.         }
  778.     else {
  779.         lCharWidth = 217 ;
  780.         lCharHeight = 465 ;
  781.         }
  782.     PrfCloseProfile( hini ) ;
  783.  
  784.     if( qPrintData.szPrinterName[0] == '\0' ) {
  785.             // get default printer name    
  786.         PrfQueryProfileString( HINI_PROFILE,
  787.                                "PM_SPOOLER",
  788.                                "PRINTER",
  789.                                ";",
  790.                                qPrintData.szPrinterName,
  791.                                (long) sizeof qPrintData.szPrinterName ) ;
  792.         if( (p=strchr( qPrintData.szPrinterName, ';' )) != NULL ) *p = '\0' ;
  793.         }
  794.     bShellPos = bPos ;
  795.     return bPos ;
  796.     }
  797.  
  798. static void SaveIni( HWND hWnd )
  799. /*
  800. ** save data in ini file
  801. */
  802.     {
  803.     SWP     swp ;
  804.     HINI    hini ;
  805.     ULONG   ulOpts[5] ;
  806.     HFILE   hfile ;
  807.     ULONG   ulAct ;
  808.     ERRORID errid ;
  809.     char    achErr[64] ;
  810.     HAB     hab ;
  811.  
  812.     hab = WinQueryAnchorBlock( hWnd ) ;    
  813.     hini = PrfOpenProfile( hab, szIniFile ) ;
  814.     if( hini != NULLHANDLE ) {
  815.         WinQueryWindowPos( hwndFrame, &swp ) ;
  816.         ulPlotPos[0] = swp.x ;
  817.         ulPlotPos[1] = swp.y ;
  818.         ulPlotPos[2] = swp.cx ;
  819.         ulPlotPos[3] = swp.cy ;
  820.         PrfWriteProfileData( hini, APP_NAME, INISHELLPOS, &ulPlotPos, sizeof(ulPlotPos) ) ;
  821.         if( pausedata.pswp != NULL )
  822.             PrfWriteProfileData( hini, APP_NAME, INIPAUSEPOS, 
  823.                                  pausedata.pswp, sizeof(SWP) ) ;
  824.         ulOpts[0] = (ULONG)bLineTypes ;
  825.         ulOpts[1] = (ULONG)bWideLines ; 
  826.         ulOpts[2] = (ULONG)bColours ;
  827.         ulOpts[3] = ulPauseMode ; 
  828.         ulOpts[4] = (ULONG)bPopFront ; 
  829.         PrfWriteProfileData( hini, APP_NAME, INIOPTS, &ulOpts, sizeof(ulOpts) ) ;
  830.         PrfWriteProfileData( hini, APP_NAME, INIFRAC, &qPrintData.xsize, 4*sizeof(float) ) ;
  831.         if( qPrintData.pdriv != NULL )
  832.             PrfWriteProfileData( hini, APP_NAME, INIPRDRIV, qPrintData.pdriv, 
  833.                                  qPrintData.cbpdriv ) ;
  834.         PrfWriteProfileString( hini, APP_NAME, INIPRPR, 
  835.                                qPrintData.szPrinterName[0] == '\0'? NULL:
  836.                                qPrintData.szPrinterName ) ;
  837.         PrfWriteProfileString( hini, APP_NAME, INIFONT, szFontNameSize ) ;
  838.         ulOpts[0] = (ULONG)lCharWidth ;
  839.         ulOpts[1] = (ULONG)lCharHeight ;
  840.         PrfWriteProfileData( hini, APP_NAME, INICHAR, &ulOpts, sizeof(ulOpts) ) ;
  841.         PrfCloseProfile( hini ) ;
  842.         }
  843.     else {
  844.         WinMessageBox( HWND_DESKTOP,
  845.                        HWND_DESKTOP,
  846.                        "Can't write ini file",
  847.                        APP_NAME,
  848.                        0,
  849.                        MB_OK | MB_ICONEXCLAMATION ) ;
  850.         }    
  851.     }
  852.  
  853. static void DoPaint( HWND hWnd, HPS hps  ) 
  854. /*
  855. **  Paint the screen with current data 
  856. */
  857.     {
  858.     ULONG ulCount ;
  859.  
  860.     static RECTL rectl ;    
  861.     if( tidDraw != 0 ) {
  862.             /* already drawing - stop it; include the rectl now
  863.                being drawn in, in the update region; and return
  864.                without calling beginpaint so that the paint 
  865.                message is resent */
  866.         GpiSetStopDraw( hpsScreen, SDW_ON ) ;
  867.         DosSleep(1) ;
  868.         WinInvalidateRect( hWnd, &rectl, TRUE ) ;
  869.         return ;
  870.         }
  871.             /* winbeginpaint here, so paint message is
  872.                not resent when we return, then spawn a 
  873.                thread to do the drawing */
  874.     WinBeginPaint( hWnd, hps, &rectl ) ;                 //rl
  875.     tidDraw = _beginthread( ThreadDraw, NULL, 32768, NULL ) ;
  876.     }
  877.  
  878. static void ThreadDraw( void* arg )
  879. /*
  880. **  Thread to draw plot on screen
  881. */
  882.     {
  883.     HAB     hab ;
  884.  
  885.     hab = WinInitialize( 0 ) ;
  886.  
  887.     InitScreenPS() ;        
  888.  
  889.     DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
  890.     ScalePS( hpsScreen ) ;
  891.     GpiSetStopDraw( hpsScreen, SDW_OFF ) ;  
  892.     GpiSetDrawingMode( hpsScreen, DM_DRAW ) ;
  893.     GpiDrawChain( hpsScreen ) ;
  894.     WinEndPaint( hpsScreen ) ;
  895.     DosReleaseMutexSem( semHpsAccess ) ;
  896.     WinTerminate( hab ) ;
  897.     tidDraw = 0 ;
  898.     }
  899.  
  900. HPS InitScreenPS()
  901. /*
  902. ** Initialise the screen ps for drawing
  903. */
  904.     {
  905.     RECTL   rectClient ;
  906.     int     nColour = 0 ;        
  907.  
  908.     GpiResetPS( hpsScreen, GRES_ATTRS ) ;
  909.     GpiErase(hpsScreen);
  910.  
  911.     WinQueryWindowRect( hApp, (PRECTL)&rectClient ) ;
  912.     {
  913.     double ratio = 1.560 ;
  914.     double xs = rectClient.xRight - rectClient.xLeft ;
  915.     double ys = rectClient.yTop - rectClient.yBottom ;
  916.     if( ys > xs/ratio ) { /* reduce ys to fit */
  917.         rectClient.yTop = rectClient.yBottom + (int)(xs/ratio) ; 
  918.         }
  919.     else if( ys < xs/ratio ) { /* reduce xs to fit */
  920.         rectClient.xRight = rectClient.xLeft + (int)(ys*ratio) ;
  921.         }
  922.     }
  923.        
  924.     GpiSetPageViewport( hpsScreen, &rectClient ) ;
  925.     if( !bColours ) {
  926.         int i ;
  927.         for( i=0; i<8; i++ ) alColourTable[i] = 0 ;
  928.         for( i=8; i<16; i++ ) alColourTable[i] = 0 ;
  929.         alColourTable[0] = 0xFFFFFF ;
  930.         nColour = 16 ;
  931.         }
  932.     GpiCreateLogColorTable( hpsScreen,
  933.                             LCOL_RESET,
  934.                             LCOLF_CONSECRGB,
  935.                             0, nColour, alColourTable ) ;
  936.     return hpsScreen ;
  937.     }
  938.  
  939. enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode;
  940.  
  941.  
  942. short ScalePS( HPS hps )
  943. /*
  944. **  Get a font to use
  945. **  Scale the plot area to world coords for subsequent plotting
  946. */
  947.     {
  948.     RECTL rectView ;
  949.         
  950.     SelectFont( hps, szFontNameSize ) ;
  951.     return 0 ;
  952.     }
  953.  
  954. static SIZEF sizBaseSubSup ;
  955. static SIZEF sizCurSubSup ;
  956. static SIZEF sizCurFont ;
  957. static long lVOffset = 0 ;
  958. static SIZEF sizBaseFont ;
  959. static struct _ft {
  960.     char *name ;
  961.     LONG  lcid ; 
  962.     } tabFont[256] = {{NULL,0L}, {NULL}};
  963.     
  964. void SelectFont( HPS hps, char *szFontNameSize )
  965. /*
  966. **  Select a named and sized outline (adobe) font
  967. */
  968.     {
  969.      HDC    hdc ;
  970.      FATTRS  fat ;
  971.      LONG   xDeviceRes, yDeviceRes ;
  972.      POINTL ptlFont ;
  973.      SIZEF  sizfx ;
  974.      static LONG lcid = 0L ;
  975.      static char *szFontName ;
  976.      static short shPointSize ;
  977.  
  978.      sscanf( szFontNameSize, "%hd", &shPointSize ) ;
  979.      szFontName = strchr( szFontNameSize, '.' ) + 1 ;
  980.  
  981.      fat.usRecordLength  = sizeof fat ;
  982.      fat.fsSelection     = 0 ;
  983.      fat.lMatch          = 0 ;
  984.      fat.idRegistry      = 0 ;
  985.      fat.usCodePage      = 0 ; //GpiQueryCp (hps) ;
  986.      fat.lMaxBaselineExt = 0 ;
  987.      fat.lAveCharWidth   = 0 ;
  988.      fat.fsType          = 0 ;
  989.      fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
  990.                            FATTR_FONTUSE_TRANSFORMABLE ;
  991.  
  992.      strcpy (fat.szFacename, szFontName) ;
  993.  
  994.      if(tabFont[0].name !=NULL) free( tabFont[0].name ) ;
  995.      tabFont[0].name = strdup( szFontName ) ;
  996.      tabFont[0].lcid = 10L ;
  997.      
  998.      lcid = GpiQueryCharSet( hps ) ;
  999.      if( lcid != 10L ) lcid = 10L ;
  1000.      else {
  1001.         GpiSetCharSet( hps, 0L) ;
  1002.         GpiDeleteSetId( hps, lcid ) ;
  1003.         }
  1004.      GpiCreateLogFont (hps, NULL, lcid, &fat) ;
  1005.      GpiSetCharSet( hps, lcid ) ;
  1006.  
  1007.      hdc = GpiQueryDevice (hps) ;
  1008.  
  1009.      DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ;
  1010.      DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION,   1L, &yDeviceRes) ;
  1011.  
  1012.                          // Find desired font size in pixels
  1013.  
  1014.      ptlFont.x = 2540L * (long)shPointSize / 72L ;
  1015.      ptlFont.y = 2540L * (long)shPointSize / 72L ;
  1016.  
  1017.                          // Set the character box
  1018.  
  1019.      sizfx.cx = MAKEFIXED (ptlFont.x, 0) ;
  1020.      sizfx.cy = MAKEFIXED (ptlFont.y, 0) ;
  1021.      lVOffset = ptlFont.y ;
  1022.  
  1023.      sizBaseFont = sizfx ;
  1024.      GpiSetCharBox (hps, &sizfx) ;
  1025.  
  1026.                         // set up some useful globals
  1027.      {
  1028.      FONTMETRICS fm ;
  1029.      GpiQueryFontMetrics( hps, sizeof(FONTMETRICS), &fm ) ;
  1030.      lBaseSubOffset = -fm.lSubscriptYOffset ;
  1031.      lBaseSupOffset = fm.lSuperscriptYOffset ;
  1032.      lSubOffset = lBaseSubOffset ;
  1033.      lSupOffset = lBaseSupOffset ;
  1034.      lCharHeight = fm.lMaxAscender*1.2 ;
  1035.      lCharWidth  = fm.lAveCharWidth ;
  1036.      sizBaseSubSup.cx = MAKEFIXED( ptlFont.x*0.7, 0 ) ; 
  1037.      sizBaseSubSup.cy = MAKEFIXED( ptlFont.y*0.7, 0 ) ; 
  1038.      }
  1039.      sizCurFont = sizBaseFont ;
  1040.      sizCurSubSup = sizBaseSubSup ;
  1041.     if( bNewFont ) {
  1042. //        EditCharCell( hps, &sizfx ) ;
  1043.         bNewFont = FALSE ;
  1044.         }
  1045.     }
  1046.  
  1047. void SwapFont( HPS hps, char *szFNS )
  1048. /*
  1049. **  Select a named and sized outline (adobe) font
  1050. */
  1051.     {
  1052.      HDC    hdc ;
  1053.      FATTRS  fat ;
  1054.      LONG   xDeviceRes, yDeviceRes ;
  1055.      POINTL ptlFont ;
  1056.      SIZEF  sizfx ;
  1057.      static LONG lcid = 0L ;
  1058.      static int itab = 1 ;
  1059.      static char *szFontName ;
  1060.      static short shPointSize ;
  1061.  
  1062.      if( szFNS == NULL ) {    /* restore base font */
  1063.          sizCurFont = sizBaseFont ;
  1064.          sizCurSubSup = sizBaseSubSup ;
  1065.          lSubOffset = lBaseSubOffset ;
  1066.          lSupOffset = lBaseSupOffset ;
  1067.          GpiSetCharSet( hps, 10 ) ;
  1068.          GpiSetCharBox (hps, &sizBaseFont) ;
  1069.         }
  1070.      else {
  1071.         sscanf( szFNS, "%hd", &shPointSize ) ;
  1072.         szFontName = strchr( szFNS, '.' ) + 1 ;
  1073.  
  1074.         {
  1075.             int i ;
  1076.             lcid = 0 ;
  1077.             for(i=0;i<itab;i++) {
  1078.                 if( strcmp( szFontName, tabFont[i].name ) == 0 ) {
  1079.                     lcid = tabFont[i].lcid ;
  1080.                     break ;
  1081.                     }
  1082.                 }
  1083.         }
  1084.         if( lcid == 0 ) {   
  1085.  
  1086.         fat.usRecordLength  = sizeof fat ;
  1087.         fat.fsSelection     = 0 ;
  1088.         fat.lMatch          = 0 ;
  1089.         fat.idRegistry      = 0 ;
  1090.         fat.usCodePage      = 0 ; //GpiQueryCp (hps) ;
  1091.         fat.lMaxBaselineExt = 0 ;
  1092.         fat.lAveCharWidth   = 0 ;
  1093.         fat.fsType          = 0 ;
  1094.         fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
  1095.                                FATTR_FONTUSE_TRANSFORMABLE ;
  1096.  
  1097.         strcpy (fat.szFacename, szFontName) ;
  1098.  
  1099.  
  1100.         tabFont[itab].name = strdup( szFontName ) ;
  1101.         lcid = itab+10 ;
  1102.         tabFont[itab].lcid = lcid ;
  1103.         ++itab ;
  1104.  
  1105. //        lcid = 11L ;
  1106.         GpiSetCharSet( hps, 0L) ;
  1107.         GpiDeleteSetId( hps, lcid ) ;
  1108.         GpiCreateLogFont (hps, NULL, lcid, &fat) ;
  1109.         }
  1110.         GpiSetCharSet( hps, lcid ) ;
  1111.      hdc = GpiQueryDevice (hps) ;
  1112.  
  1113.      DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ;
  1114.      DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION,   1L, &yDeviceRes) ;
  1115.  
  1116.                          // Find desired font size in pixels
  1117.  
  1118.      ptlFont.x = 2540L * (long)shPointSize / 72L ;
  1119.      ptlFont.y = 2540L * (long)shPointSize / 72L ;
  1120.  
  1121.                          // Set the character box
  1122.  
  1123.      sizCurFont.cx = MAKEFIXED (ptlFont.x, 0) ;
  1124.      sizCurFont.cy = MAKEFIXED (ptlFont.y, 0) ;
  1125. //     lVOffset = ptlFont.y ;
  1126.  
  1127.      GpiSetCharBox (hps, &sizCurFont) ;
  1128.      sizCurSubSup.cx = MAKEFIXED( ptlFont.x*0.7, 0 ) ; 
  1129.      sizCurSubSup.cy = MAKEFIXED( ptlFont.y*0.7, 0 ) ; 
  1130.  
  1131.                         // set up some useful globals
  1132.      {
  1133.      FONTMETRICS fm ;
  1134.      GpiQueryFontMetrics( hps, sizeof(FONTMETRICS), &fm ) ;
  1135.      lSubOffset = -fm.lSubscriptYOffset ;
  1136.      lSupOffset = fm.lSuperscriptYOffset ;
  1137.      }
  1138.         }
  1139.         
  1140.      }
  1141.  
  1142. static void ReadGnu( void* arg )
  1143. /*
  1144. ** Thread to read plot commands from  GNUPLOT pm driver.
  1145. ** Opens named pipe, then clears semaphore to allow GNUPLOT driver to proceed.
  1146. ** Reads commands and builds a command list.
  1147. */
  1148.     {
  1149.     HPIPE    hRead = 0L ; 
  1150.     POINTL ptl ;
  1151.     POINTL aptl[4] ;    
  1152.     long lCurCol ;
  1153.     long lOldLine = 0 ;
  1154.     BOOL bBW = FALSE ; /* passed frpm print.c ?? */
  1155.     BOOL bPath = FALSE ;
  1156.     BOOL bDots = FALSE ;
  1157.     char *szEnv ;
  1158.     char *szFileBuf ;
  1159.     ULONG rc; 
  1160.     USHORT usErr ;
  1161.     ULONG cbR ;
  1162.     USHORT i ;
  1163.     PID ppid ;
  1164.     unsigned char buff[2] ;
  1165.     HEV hev ;
  1166.     static char *szPauseText = NULL ;
  1167.     ULONG ulPause ;
  1168.     char *pszPipeName, *pszSemName ;
  1169.     LONG  commands[4] ;
  1170.     HPS hps ;    
  1171.     HAB hab ;
  1172.     int linewidth = DEFLW ;
  1173.  
  1174.     hab = WinInitialize( 0 ) ;
  1175.     DosEnterCritSec() ;
  1176.     pszPipeName = malloc( 256 ) ;
  1177.     pszSemName  = malloc( 256 ) ;
  1178.     DosExitCritSec() ;
  1179.     strcpy( pszPipeName, "\\pipe\\" ) ;
  1180.     strcpy( pszSemName, "\\sem32\\" ) ;
  1181.     strcat( pszPipeName, szIPCName ) ;
  1182.     strcat( pszSemName, szIPCName ) ;
  1183.  
  1184.             /* open a named pipe for communication with gnuplot */
  1185.  
  1186.     rc = DosCreateNPipe( pszPipeName,
  1187.                          &hRead, 
  1188.                          NP_ACCESS_DUPLEX|NP_NOINHERIT|NP_NOWRITEBEHIND ,
  1189.                          1|NP_WAIT|NP_READMODE_MESSAGE|NP_TYPE_MESSAGE,
  1190.                          PIPEBUF,
  1191.                          PIPEBUF,
  1192.                          0xFFFFFFFF) ;
  1193.     hev = 0 ;       /* OK, gnuplot can try to open npipe ... */
  1194.     DosOpenEventSem( pszSemName, &hev ) ;
  1195.     DosPostEventSem( hev ) ;
  1196.     
  1197.  
  1198.     
  1199.         /* attach to gnuplot */
  1200.  
  1201. server:
  1202.  
  1203.     if( DosConnectNPipe( hRead ) == 0L ) {
  1204.  
  1205.         WinPostMsg( hSysMenu,
  1206.                     MM_SETITEMATTR,
  1207.                     MPFROM2SHORT(SC_CLOSE, TRUE ),
  1208.                     MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED) ) ;
  1209.  
  1210.         /* store graphics commands */
  1211.         /* use semaphore to prevent problems with drawing while reallocating
  1212.            the command buffers */
  1213.  
  1214.         DosRead( hRead, &ppidGnu, 4, &cbR ) ;
  1215. //        DosPostEventSem( semStartSeq ) ;         /* once we've got pidGnu */
  1216.         WinPostMsg( hApp, WM_GPSTART, 0, 0 ) ;
  1217.  
  1218.  
  1219.         hps = hpsScreen ;
  1220.    InitScreenPS() ;
  1221.         while (1) {
  1222.         
  1223.             usErr=BufRead(hRead,buff, 1, &cbR) ;
  1224.             if( usErr != 0 ) break ;
  1225.  
  1226.             switch( *buff ) {
  1227.                 case 'G' :    /* enter graphics mode */
  1228.                     {
  1229.                     ULONG ulCount ;    
  1230.                     
  1231.                     if( tidDraw != 0 ) {
  1232.                       /* already drawing - stop it */
  1233.                         GpiSetStopDraw( hpsScreen, SDW_ON ) ;
  1234.                         while(tidDraw != 0) DosSleep(1) ;
  1235.                         }
  1236.                     /* wait for access to command list and lock it */
  1237. //                    DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;                    
  1238. //                    DosEnterCritSec() ;
  1239.                     DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
  1240.                     InitScreenPS() ;
  1241.                     ScalePS( hps ) ;
  1242. //                    DosResetEventSem( semDrawDone, &ulCount ) ;
  1243.                     GpiSetDrawingMode( hps, DM_DRAWANDRETAIN ) ;
  1244.                     for(i=1;i<=iSeg;i++)
  1245.                         GpiDeleteSegment( hps, i ) ;
  1246.                     iSeg = 1 ;
  1247.                     GpiOpenSegment( hps, iSeg ) ;
  1248. //                    DosExitCritSec() ;
  1249.                     GpiSetLineEnd( hps, LINEEND_ROUND ) ;
  1250.                     GpiSetLineWidthGeom( hps, linewidth ) ;
  1251.                     GpiSetCharBox (hps, &sizBaseFont) ;
  1252.                     }
  1253.                     break ;
  1254.                     
  1255.                 case 'Q' :     /* query terminal info */
  1256.                     DosWrite( hRead, &lCharWidth, sizeof(int), &cbR ) ;
  1257.                     DosWrite( hRead, &lCharHeight, sizeof(int), &cbR ) ;
  1258.                     break ;
  1259.  
  1260.                 case 'E' :     /* leave graphics mode (graph completed) */
  1261.                     if( bPath ) {
  1262.                         GpiEndPath( hps ) ;
  1263.                         GpiStrokePath( hps, 1, 0 ) ;
  1264.                         bPath = FALSE ;
  1265.                         }
  1266.                     GpiCloseSegment( hps ) ;
  1267. //                    DosPostEventSem( semDrawDone ) ;
  1268.                     DosReleaseMutexSem( semHpsAccess ) ;
  1269.                     WinPostMsg( hApp, WM_GNUPLOT, 0L, 0L ) ;
  1270.                     break ;
  1271.                     
  1272.                 case 'R' :
  1273.                     /* gnuplot has reset drivers, allow user to kill this */
  1274.                     WinPostMsg( hSysMenu,
  1275.                                 MM_SETITEMATTR,
  1276.                                 MPFROM2SHORT(SC_CLOSE, TRUE ),
  1277.                                 MPFROM2SHORT(MIA_DISABLED, (USHORT)0 ) ) ;
  1278.                     /* if we are keeping us on the screen, wait for new connection */
  1279.                     if( bServer||bPersist ) {
  1280.                         DosDisConnectNPipe( hRead ) ;
  1281.                         goto server ;
  1282.                         }    
  1283.                     break ;
  1284.                 
  1285.                 case 'r' :
  1286.                     /* resume after multiplot */
  1287.                     {
  1288.                     ULONG ulCount ;    
  1289.                     DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
  1290. //                    DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;
  1291.                     iSeg++ ;
  1292. //                    DosResetEventSem( semDrawDone, &ulCount ) ;
  1293.                     GpiSetDrawingMode( hps, DM_DRAWANDRETAIN ) ;
  1294.                     GpiOpenSegment( hps, iSeg ) ;
  1295.                     }
  1296.                     break ;
  1297.                     
  1298.                 case 's' :
  1299.                     /* suspend after multiplot */
  1300.                     break ;
  1301.  
  1302.                 case 'M' :   /* move */
  1303.                 case 'V' :   /* draw vector */
  1304.                     if( *buff=='M' ) {
  1305.                         if( bPath ) {
  1306.                             GpiEndPath( hps ) ;
  1307.                             GpiStrokePath( hps, 1, 0 ) ;
  1308.                             bPath = FALSE ;
  1309.                             }
  1310.                         }
  1311.                     else {
  1312.                         if( bWideLines/*bWideLines*/ && !bPath ) {
  1313.                             GpiBeginPath( hps, 1 ) ;
  1314.                             bPath = TRUE ;
  1315.                             }
  1316.                         }
  1317.                     BufRead(hRead,&ptl.x, 2*sizeof(int), &cbR) ;
  1318.                     if( (*buff=='V') && bDots ) ptl.x += 5 ;
  1319.                     else if( (*buff=='M') && bDots ) ptl.x -= 5 ;
  1320.                     if( *buff == 'M' ) LMove( hps, &ptl ) ;
  1321.                     else LLine( hps, &ptl ) ;
  1322.                     break ;
  1323.                   
  1324.                 case 'P' :   /* pause */
  1325.                     {
  1326.                     int len ;
  1327.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  1328.                     len = (len+sizeof(int)-1)/sizeof(int) ;
  1329.                     if( len > 0 ){  /* get pause text */
  1330.                         DosEnterCritSec() ;
  1331.                         szPauseText = malloc( len*sizeof(int) ) ;
  1332.                         DosExitCritSec() ;
  1333.                         BufRead(hRead,szPauseText, len*sizeof(int), &cbR) ;
  1334.                         }
  1335.                     if( ulPauseMode != PAUSE_GNU ) {
  1336.                              /* pause and wait for semaphore to be cleared */
  1337.                         DosResetEventSem( semPause, &ulPause ) ;
  1338.                         WinPostMsg( hApp, WM_PAUSEPLOT, (MPARAM) szPauseText, 0L ) ;
  1339.                         DosWaitEventSem( semPause, SEM_INDEFINITE_WAIT ) ;
  1340.                         }
  1341.                     else { /* gnuplot handles pause */
  1342.                         ulPauseReply = 2 ;
  1343.                         }
  1344.                     DosEnterCritSec() ;
  1345.                     if( szPauseText != NULL ) free( szPauseText ) ;
  1346.                     szPauseText = NULL ;
  1347.                     DosExitCritSec() ;
  1348.                              /* reply to gnuplot so it can continue */
  1349.                     DosWrite( hRead, &ulPauseReply, sizeof(int), &cbR ) ;
  1350.                     }
  1351.                     break ; 
  1352.                        
  1353.                 case 'T' :   /* write text */
  1354.                         /* read x, y, len */
  1355.                     if( bPath ) {
  1356.                         GpiEndPath( hps ) ;
  1357.                         GpiStrokePath( hps, 1, 0 ) ;
  1358.                         bPath = FALSE ;
  1359.                         }
  1360.                     {
  1361.                     int x, y, len, sw ;
  1362.                     char *str ;
  1363.                     BufRead(hRead,&x, sizeof(int), &cbR) ;
  1364.                     BufRead(hRead,&y, sizeof(int), &cbR) ;
  1365.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  1366.  
  1367.                     DosEnterCritSec() ;
  1368.                     len = (len+sizeof(int)-1)/sizeof(int) ;
  1369.                     if( len == 0 ) len = 1 ; //?? how about read
  1370.                     str = malloc( len*sizeof(int) ) ;
  1371.                     *str = '\0' ;
  1372.                     DosExitCritSec() ;
  1373.                     BufRead(hRead, str, len*sizeof(int), &cbR) ;
  1374.                     lCurCol = GpiQueryColor( hps ) ;
  1375.                     GpiSetColor( hps, CLR_BLACK ) ;
  1376.                     sw = QueryTextBox( hps, strlen(str), str ) ; 
  1377.                     switch(jmode) {
  1378.                     case LEFT:   sw = 0;     break;
  1379.                     case CENTRE: sw = -sw/2; break;
  1380.                     case RIGHT:  sw = -sw;   break;
  1381.                         }
  1382.                     if( bHorz ) {
  1383.                         ptl.x = (LONG)(x+sw) ; ptl.y = (LONG)(y-lVOffset/4) ;
  1384.                         }
  1385.                     else {
  1386.                         ptl.x = (LONG)x ; ptl.y = (LONG)(y+sw) ;
  1387.                         }
  1388.                     if(bEnhanced)
  1389.                         CharStringAt( hps, ptl.x, ptl.y, strlen( str ) , str ) ;
  1390.                     else
  1391.                         GpiCharStringAt( hps, &ptl, strlen( str ), str ) ;
  1392.                     GpiSetColor( hps, lCurCol ) ;
  1393.                     DosEnterCritSec() ;
  1394.                     free(str) ;
  1395.                     DosExitCritSec() ;
  1396.                     }
  1397.                     break ;
  1398.                     
  1399.                 case 'J' :   /* justify */
  1400.                     BufRead(hRead,&jmode, sizeof(int), &cbR) ;
  1401.                     break ;
  1402.  
  1403.                 case 'A' :   /* text angle */
  1404.                     {
  1405.                     int ta ;    
  1406.                     GRADIENTL grdl ;
  1407.                     SIZEF sizHor, sizVer ;
  1408.                     if( bPath ) {
  1409.                         GpiEndPath( hps ) ;
  1410.                         GpiStrokePath( hps, 1, 0 ) ;
  1411.                         bPath = FALSE ;
  1412.                         }
  1413.                     BufRead(hRead,&ta, sizeof(int), &cbR) ;
  1414.                     if( ta == 0 ) {
  1415.                         grdl.x = 0L ; grdl.y = 0L ;
  1416.                         GpiSetCharAngle( hps, &grdl ) ;
  1417.                         if( !bHorz ) {
  1418.                             bHorz = TRUE ;
  1419.                             }
  1420.                         }
  1421.                     else if( ta == 1 ) {
  1422.                         grdl.x = 0L ; grdl.y = 1L ;
  1423.                         GpiSetCharAngle( hps, &grdl ) ;
  1424.                         if( bHorz ) {
  1425.                             bHorz = FALSE ;
  1426.                             }
  1427.                         }
  1428.                     }
  1429.                     break ;
  1430.  
  1431.                 case 'L' :   /* line type */
  1432.                     {
  1433.                     int lt, col ;
  1434.                     if( bPath ) {
  1435.                         GpiEndPath( hps ) ;
  1436.                         GpiStrokePath( hps, 1, 0 ) ;
  1437.                         bPath = FALSE ;
  1438.                         }
  1439.                     BufRead(hRead,<, sizeof(int), &cbR) ;
  1440.                 /* linetype = -2 axes, -1 border, 0 arrows, all to 0 */
  1441.                 col = lt ;
  1442.                     if( lt == -2 )     GpiSetLineWidthGeom( hps, DEFLW*0.85 ) ;
  1443.                     else if( lt == -1 ) GpiSetLineWidthGeom( hps, DEFLW*0.6 ) ;
  1444.                     else GpiSetLineWidthGeom( hps, linewidth ) ;
  1445.                     if( lt < 0 ) lt = 0 ;
  1446.                 lt = (lt%8);
  1447.                 col = (col+2)%16 ;
  1448.                     GpiLabel( hps, lLineTypes[lt] ) ;
  1449. lOldLine=lt ;
  1450.                     LType( (bLineTypes||bBW)?lt:0 ) ;
  1451. //                    GpiSetLineType( hps, (bLineTypes||bBW)?lLineTypes[lt]:lLineTypes[0] ) ;
  1452.                     if( !bBW ) { /* maintain some flexibility here in case we don't want
  1453.                            the model T option */ 
  1454.                         if( bColours ) GpiSetColor( hps, lCols[col] ) ;
  1455.                         else GpiSetColor( hps, CLR_BLACK ) ;
  1456.                         }
  1457.                     }
  1458.                     break ;
  1459.                     
  1460.                 case 'W' :   /* line width */
  1461.                     {
  1462.                     int lw ;
  1463.                     if( bPath ) {
  1464.                         GpiEndPath( hps ) ;
  1465.                         GpiStrokePath( hps, 1, 0 ) ;
  1466.                         bPath = FALSE ;
  1467.                         }
  1468.                     BufRead(hRead,&lw, sizeof(int), &cbR) ;
  1469.                     GpiSetLineWidthGeom( hps, DEFLW*lw/100 ) ;
  1470.                     linewidth = DEFLW*lw/100 ;
  1471.                     }
  1472.                     break ;
  1473.                     
  1474.                  case 'D' :   /* points mode */
  1475.                     {
  1476.                     int lt ;
  1477.                     BufRead(hRead,<, sizeof(int), &cbR) ;
  1478.                       /* 1: enter point mode, 0: exit */
  1479.                     if( bLineTypes || bBW ) {
  1480.                         if( lt==1) LType(0) ;
  1481.                         else LType( lOldLine ) ;
  1482. //                        if( lt == 1 ) lOldLine = GpiSetLineType( hps, lLineTypes[0] ) ;
  1483. //                        else GpiSetLineType( hps, lOldLine ) ;
  1484.                         }
  1485. //                    if( lt == 1 ) GpiSetLineWidthGeom( hps, 20 ) ;
  1486. //                    else GpiSetLineWidthGeom( hps, 50 ) ;
  1487.                     bDots = lt ;
  1488.                     }
  1489.                     break ;
  1490.                 
  1491.                 case 'F' :   /* set font */
  1492.  
  1493.                     {
  1494.                     int len ;
  1495.                     char *str ;
  1496.                     char font[FONTBUF] ;
  1497.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  1498.                     len = (len+sizeof(int)-1)/sizeof(int) ;
  1499.                     if( len == 0 ) {
  1500.                         SwapFont( hps, NULL ) ;
  1501.                         }
  1502.                     else {
  1503.                         char *p ;
  1504.                         str = malloc( len*sizeof(int) ) ;
  1505.                         BufRead(hRead, str, len*sizeof(int), &cbR) ;
  1506.                         p = strchr(str, ',') ;
  1507.                         if( p==NULL ) strcpy( font, "14" ) ;
  1508.                         else {
  1509.                             *p = '\0' ;
  1510.                             strcpy( font, p+1 ) ;
  1511.                             }
  1512.                         strcat( font,"." ) ;
  1513.                         strcat( font, str ) ;
  1514.                         free( str ) ;
  1515.                         SwapFont( hps, font ) ;
  1516.                         } 
  1517.                     }
  1518.                     break ;
  1519.                     
  1520.                 case 'O' :   /* set options */
  1521.  
  1522.                     {
  1523.                     int len ;
  1524.                     char *str ;
  1525.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  1526.                     len = (len+sizeof(int)-1)/sizeof(int) ;
  1527.                     bWideLines = FALSE ; /* reset options */
  1528.                     bEnhanced = FALSE ;
  1529.                     
  1530.                     if( len > 0 ) {
  1531.                         char *p ;
  1532.                         p = str = malloc( len*sizeof(int) ) ;
  1533.                         BufRead(hRead, str, len*sizeof(int), &cbR) ;
  1534.                         while( (p=strchr(p,'-')) != NULL ) {
  1535.                             ++p ;
  1536.                             if( *p == 'w' ) bWideLines = TRUE ;
  1537.                             if( *p == 'e' ) bEnhanced = TRUE ;
  1538.                             ++p ;
  1539.                             }
  1540.                         free( str ) ;
  1541.                         } 
  1542.                     }
  1543.                     break ;
  1544.                 
  1545.  
  1546.                  default :  /* should handle error */
  1547.                     break ;
  1548.                  }
  1549.              }
  1550.         }
  1551. exitserver:
  1552.     DosDisConnectNPipe( hRead ) ;
  1553.     WinPostMsg( hApp, WM_CLOSE, 0L, 0L ) ;    
  1554.     }
  1555.  
  1556. static void EditLineTypes( HWND hwnd, HPS hps, BOOL bDashed )
  1557. /*
  1558. */
  1559.     {
  1560.     int i, rc ;
  1561.     char buf[64] ;
  1562.     GpiSetDrawingMode( hps, DM_RETAIN ) ;
  1563.     GpiOpenSegment( hps, iSeg ) ;
  1564.     GpiSetEditMode( hps, SEGEM_REPLACE ) ;
  1565.     for( i=0; i<7; i++ ) {
  1566.         while( GpiSetElementPointerAtLabel( hps, lLineTypes[i] ) ) {
  1567.             GpiOffsetElementPointer( hps, 1 ) ;
  1568.             GpiSetLineType( hps, bDashed?lLineTypes[i]:lLineTypes[0] ) ;
  1569.             }
  1570.         GpiSetElementPointer( hps, 0 ) ;
  1571.         }    
  1572.     GpiSetEditMode( hps, SEGEM_INSERT ) ;
  1573.     GpiCloseSegment( hps ) ;    
  1574.     }
  1575.  
  1576. static void EditCharCell( HPS hps, SIZEF *psize )
  1577. /*
  1578. ** Edit segment to change char cell (font size)
  1579. */
  1580.     {
  1581.     int i ;
  1582.     LONG rl, rc ;
  1583.     SIZEF sizH, sizV ;
  1584.     char buf[64] ;
  1585.     int iVert = 0 ;
  1586.     
  1587.     sizH = *psize ;
  1588.     sizV.cx = sizH.cy ;
  1589.     sizV.cy = sizH.cx ;
  1590.     GpiSetDrawingMode( hps, DM_RETAIN ) ;
  1591.     GpiOpenSegment( hps, iSeg ) ;
  1592.     GpiSetEditMode( hps, SEGEM_REPLACE ) ;
  1593.     i=0 ;
  1594.     while( GpiSetElementPointer( hps, i ) ) {
  1595.         rc = GpiQueryElementPointer( hps) ;
  1596.         if( rc != i ) break ;
  1597.         rl = GpiQueryElementType( hps, &rc, 0, NULL ) ;
  1598.         if( rc == 0x34 || rc == 0x74 ) {
  1599.             LONG gdata ;
  1600.             GpiQueryElement( hps, 5, 4, (PBYTE)&gdata ) ;
  1601.             if( gdata == 0 ) iVert = 0 ;
  1602.             else iVert = 1 ; 
  1603.             }
  1604.         else if( rc==0x33 || rc==0x03 ) GpiSetCharBox(hps, iVert?&sizV:&sizH ) ;
  1605.         ++i ;
  1606.         }
  1607.     GpiSetEditMode( hps, SEGEM_INSERT ) ;
  1608.     GpiCloseSegment( hps ) ;    
  1609.     }
  1610.  
  1611. static int BufRead( HFILE hfile, void *buf, int nBytes, ULONG *pcbR )
  1612. /*
  1613. ** pull next plot command out of buffer read from GNUPLOT
  1614. */
  1615.     {
  1616.     ULONG ulR, ulRR ;
  1617.     int rc ;
  1618.     static char buffer[GNUBUF] ;
  1619.     static char *pbuffer = buffer+GNUBUF, *ebuffer = buffer+GNUBUF ;
  1620.     
  1621.     for( ; nBytes > 0 ; nBytes-- ) {
  1622.         if( pbuffer >= ebuffer ) {
  1623.             ulR = GNUBUF ;
  1624.             rc = DosRead( hfile, buffer, ulR, &ulRR ) ;
  1625.             if( rc != 0 ) return rc ;
  1626.             if( ulRR == 0 ) return 1 ;
  1627.             pbuffer = buffer ;
  1628.             ebuffer = pbuffer+ulRR ;
  1629.             }
  1630.         *(char*)buf++ = *pbuffer++ ;
  1631.         }
  1632.     return 0L ;
  1633.     } 
  1634.  
  1635.  
  1636. int GetNewFont( HWND hwnd, HPS hps ) 
  1637. /*
  1638. ** Get a new font using standard font dialog
  1639. */
  1640.     {
  1641.     static FONTDLG pfdFontdlg;      /* Font dialog info structure */
  1642.     static int i1 =1 ;
  1643.     static int     iSize ;
  1644.     char szPtList[64] ;
  1645.     HWND    hwndFontDlg;     /* Font dialog window handle */
  1646.     char    *p ; 
  1647.     char szFamilyname[FACESIZE];
  1648.  
  1649.     if( i1 ) {
  1650.         strcpy( pfdFontdlg.fAttrs.szFacename, strchr( szFontNameSize, '.' ) + 1 ) ;
  1651.         strcpy( szFamilyname, strchr( szFontNameSize, '.' ) + 1 ) ;
  1652.         sscanf( szFontNameSize, "%d", &iSize ) ;
  1653.         memset(&pfdFontdlg, 0, sizeof(FONTDLG));
  1654.  
  1655.         pfdFontdlg.cbSize = sizeof(FONTDLG);
  1656.         pfdFontdlg.hpsScreen = hps;
  1657.  /*   szFamilyname[0] = 0;*/
  1658.         pfdFontdlg.pszFamilyname = szFamilyname;
  1659.         pfdFontdlg.usFamilyBufLen = FACESIZE;
  1660.         pfdFontdlg.fl = FNTS_HELPBUTTON | 
  1661.                         FNTS_CENTER | FNTS_VECTORONLY | 
  1662.                         FNTS_OWNERDRAWPREVIEW ; 
  1663.         pfdFontdlg.clrFore = CLR_BLACK;
  1664.         pfdFontdlg.clrBack = CLR_WHITE;
  1665.         pfdFontdlg.usWeight = FWEIGHT_NORMAL ; //5 ;
  1666.         pfdFontdlg.fAttrs.usCodePage = 0;
  1667.         pfdFontdlg.fAttrs.usRecordLength = sizeof(FATTRS) ;
  1668.         }
  1669.     sprintf( szPtList, "%d 8 10 12 14 18 24", iSize ) ;
  1670.     pfdFontdlg.pszPtSizeList = szPtList ;
  1671.     pfdFontdlg.fxPointSize = MAKEFIXED(iSize,0); 
  1672.     hwndFontDlg = WinFontDlg(HWND_DESKTOP, hwnd, &pfdFontdlg);
  1673.     if( i1 ) {
  1674.         pfdFontdlg.fl = FNTS_HELPBUTTON | 
  1675.                         FNTS_CENTER | FNTS_VECTORONLY | 
  1676.                         FNTS_INITFROMFATTRS ; 
  1677.         i1=0; 
  1678.         } 
  1679.     if (hwndFontDlg && (pfdFontdlg.lReturn == DID_OK)) {
  1680.         iSize = FIXEDINT( pfdFontdlg.fxPointSize ) ;
  1681.         sprintf( szFontNameSize, "%d.%s", iSize, pfdFontdlg.fAttrs.szFacename ) ;
  1682.         return 1 ;
  1683.         }
  1684.     else return 0 ;
  1685.     }
  1686.  
  1687. void SigHandler( int sig )
  1688. /*
  1689. **  Handle termination signal to free up resources before
  1690. **  termination.
  1691. */
  1692.     {
  1693.     if( sig == SIGTERM ) {
  1694.         if( bPersist ) {
  1695.             DosKillThread( tidSpawn ) ;
  1696.             signal( SIGTERM, SIG_ACK ) ;
  1697.             return ;
  1698.             }
  1699.         DosEnterCritSec() ;
  1700.         DosKillThread( tidSpawn ) ;
  1701.         DosKillThread( tidDraw ) ;
  1702.         DosExitCritSec() ;
  1703.         exit(0) ;
  1704.         }
  1705.     }
  1706.  
  1707. /* disable debugging info */
  1708. #define TEXT_DEBUG(x) /* fprintf x; */
  1709.  
  1710. /* used in determining height of processed text */
  1711.  
  1712. //static float max_height, min_height;
  1713.  
  1714. /* process a bit of string, and return the last character used.
  1715.  * p is start of string
  1716.  * brace is TRUE to keep processing to }, FALSE for do one character
  1717.  * fontname & fontsize are obvious
  1718.  * base is the current baseline
  1719.  * widthflag is TRUE if the width of this should count,
  1720.  *              FALSE for zero width boxes
  1721.  * showflag is TRUE if this should be shown,
  1722.  *             FALSE if it should not be shown (like TeX \phantom)
  1723.  */
  1724.  
  1725. static char *starttext = NULL ;
  1726. static int  textlen = 0 ;
  1727. static BOOL bText = FALSE ;
  1728. static int  textwidth = 0 ;
  1729. static POINTL ptlText ;
  1730. static FILE *ff ;
  1731. static char *ParseText(HPS hps, char *p, BOOL brace, char *fontname,
  1732.                        int fontsize, int base, BOOL widthflag, BOOL showflag)
  1733. {
  1734.     POINTL aptl[TXTBOX_COUNT] ;
  1735.     BOOL bChangeFont = FALSE ;
  1736.     TEXT_DEBUG((ff,"RECURSE WITH [%p] %s, %d %s %.1f %.1f %d %d\n", p, p, brace, fontname, fontsize, base, widthflag, showflag))
  1737.  
  1738.     /* Start each recursion with a clean string */
  1739.  
  1740. //{FILE *ff;int i=textlen;ff=fopen("deb","a");
  1741. //for(i=0;i<textlen;i++)fputc(starttext[i], ff);fputc('\n',ff) ; fclose(ff);}
  1742.         if( textlen > 0 ) {
  1743.             GpiQueryTextBox( hps, textlen, starttext, TXTBOX_COUNT, aptl ) ;
  1744.             if( bHorz ) textwidth += aptl[TXTBOX_BOTTOMRIGHT].x ;
  1745.             else        textwidth += aptl[TXTBOX_BOTTOMRIGHT].y ;
  1746.             }
  1747.         if( bText ) {
  1748.             if(textlen > 0 ) {
  1749.                 GpiCharStringAt( hps, &ptlText, textlen, starttext ) ;
  1750.                 ptlText.x += aptl[TXTBOX_CONCAT].x + (bHorz?0:(-base)) ;
  1751.                 ptlText.y += aptl[TXTBOX_CONCAT].y + (bHorz?base:0) ;
  1752.                 }
  1753.             else {
  1754.                 ptlText.x += (bHorz?0:(-base)) ;
  1755.                 ptlText.y += (bHorz?base:0) ;
  1756.                 }
  1757.             }
  1758.         textlen = 0 ;
  1759.         starttext = p ;
  1760.         if( fontname != NULL ) {
  1761.             char szFont[FONTBUF] ;
  1762.             sprintf(szFont, "%d.%s", fontsize, fontname ) ;
  1763.             SwapFont( hps, szFont ) ;
  1764.             bChangeFont = TRUE ;
  1765.             }
  1766.     if( base != 0 ) GpiSetCharBox( hps, &sizCurSubSup ) ;        
  1767.  
  1768.     for ( ; *p; ++p)
  1769.     {    int shift;
  1770.  
  1771.         switch (*p)
  1772.         {
  1773.             case '}'  :
  1774.                 /*{{{  deal with it*/
  1775.                 if (brace) {
  1776.                     brace = 0 ;
  1777.                     break ;
  1778.                     }
  1779.                 
  1780.                 break;
  1781.                 /*}}}*/
  1782.         
  1783.             case '_'  :
  1784.             case '^'  :
  1785.                 /*{{{  deal with super/sub script*/
  1786.                 
  1787.                 shift = (*p == '^') ? lSupOffset : lSubOffset;
  1788.                 p = ParseText(hps, p+1, FALSE, NULL/*fontname*/, fontsize*0.7, base+shift, widthflag, showflag);                
  1789.                 break;
  1790.                 /*}}}*/
  1791.         
  1792.             case '{'  :
  1793.             {
  1794.                 char *savepos=NULL, save=0;
  1795.                 char *localfontname=fontname, ch;
  1796.                 char localfontbuf[FONTBUF] ;
  1797.                 int recode=1;
  1798.                 int f=fontsize;
  1799.                 BOOL bChangeFont = FALSE ;
  1800.                 char *q=localfontbuf ;
  1801.  
  1802.                 /*{{{  recurse (possibly with a new font) */
  1803.                 
  1804.                 TEXT_DEBUG((ff,"Dealing with {\n"))
  1805.                 
  1806.                 if (*++p == '/')
  1807.                 {    /* then parse a fontname, optional fontsize */
  1808.                     while (*++p == ' ');
  1809.                     if (*p=='-')
  1810.                     {
  1811.                         recode=0;
  1812.                         while (*++p == ' ');
  1813.                     }
  1814.                     localfontname = p;
  1815.                     while ((ch = *p) > ' ' && ch != '=') {
  1816.                             localfontname=localfontbuf ;
  1817.                             if(*p=='_') *q=' ' ;
  1818.                             else *q=*p ;
  1819.                         ++p;++q;
  1820.                         }
  1821.                     *q = '\0' ;
  1822.                     FontExpand( localfontbuf ) ;
  1823.                     save = *(savepos=p);
  1824.                     if (ch == '=')
  1825.                     {
  1826.                         *p++ = '\0';                
  1827.                         /*{{{  get optional font size*/
  1828.                         TEXT_DEBUG((ff,"Calling strtod(%s) ...", p))
  1829.                         f = strtod(p, &p);
  1830.                         TEXT_DEBUG((ff,"Retured %.1f and %s\n", f, p))
  1831.                         
  1832.                         if (!f) f = fontsize;
  1833.                         
  1834.                         TEXT_DEBUG((ff,"Font size %.1f\n", f))
  1835.                         /*}}}*/
  1836.                     }
  1837.                     else
  1838.                     {
  1839.                         *p++ = '\0';
  1840.                         f = fontsize;
  1841.                     }                
  1842.                 
  1843.                     while (*p == ' ')
  1844.                         ++p;
  1845.                     if (! (*localfontname)) {
  1846.                         localfontname = fontname;
  1847.                         if( f != fontsize ) 
  1848.                             localfontname = strchr( szFontNameSize, '.' ) + 1 ;
  1849.                         }
  1850.                 }
  1851.                 /*}}}*/
  1852.                 
  1853.                 TEXT_DEBUG((ff,"Before recursing, we are at [%p] %s\n", p, p))
  1854.         
  1855.                 p = ParseText(hps,p, TRUE, localfontname, f, base, widthflag, showflag);
  1856.                 
  1857.                 TEXT_DEBUG((ff,"BACK WITH %s\n", p));
  1858.                 if (savepos)
  1859.                     /* restore overwritten character */
  1860.                     *savepos = save;
  1861.         
  1862.                 break;
  1863.             }
  1864.                 
  1865.             case '@' :
  1866.                 /*{{{  phantom box - prints next 'char', then restores currentpoint */
  1867.                 
  1868.                 p = ParseText(hps,++p, FALSE, NULL/*fontname*/, fontsize, base, FALSE, showflag);
  1869.                     
  1870.                 break;
  1871.                 /*}}}*/
  1872.         
  1873.             case '&' :
  1874.                 /*{{{  character skip - skips space equal to length of character(s) */
  1875.                 
  1876.                 p = ParseText(hps,++p, FALSE, NULL/*fontname*/, fontsize, base, widthflag, FALSE);
  1877.                     
  1878.                 break;
  1879.                 /*}}}*/
  1880.  
  1881.             case '\\'  :
  1882.                 {
  1883.                 char buffer[4] ; /* should need only one char.. */
  1884.                 char *q = buffer ;
  1885.                 *qÎ)²7Ÿî          ParseText(hps,q, FALSE, NULL, fontsize, base, widthflag, showflag);
  1886.                 /*{{{  is it an escape */
  1887.                 /* special cases */
  1888.                 
  1889.                 if (p[1]=='\\' || p[1]=='{' || p[1]=='}')
  1890.                 {
  1891.                     *q++=p[1] ;
  1892.                     ++p ;
  1893.                 }
  1894. #if 0           
  1895.                 else if (p[1] >= '0' && p[1] <= '7')
  1896.                 {
  1897.                     /* up to 3 octal digits */
  1898.                     int c = 0 ;
  1899.                     c+=p[1];
  1900.                     ++p;
  1901.                     if (p[1] >= '0' && p[1] <= '7')
  1902.                     {
  1903.                         c*=8; c+=p[1];
  1904.                         ++p;
  1905.                         if (p[1] >= '0' && p[1] <= '7')
  1906.                         {
  1907.                             c*=8; c+=p[1];
  1908.                             ++p;
  1909.                         }
  1910.                     }
  1911.                     *q++ = c ;
  1912.                     break;
  1913.                 }
  1914. #endif          
  1915.                 *q = '\0' ;
  1916.                 textlen = 1 ;
  1917.                 starttext=buffer ;
  1918.                 ParseText(hps,q, FALSE, NULL/*fontname*/, fontsize, base, widthflag, showflag);
  1919.                 starttext=p+1 ;
  1920.                 textlen = 0 ;
  1921.                 /*}}}*/
  1922.                 }
  1923.                 break ;
  1924.  
  1925.             default: 
  1926.                 ++textlen ;                               
  1927.     
  1928.             /*}}}*/
  1929.  
  1930.         }
  1931.  
  1932.         /* like TeX, we only do one character in a recursion, unless it's
  1933.          * in braces
  1934.          */
  1935.  
  1936.         if (!brace) break ;
  1937.         }
  1938.         if( textlen > 0 ) {
  1939.             GpiQueryTextBox( hps, textlen, starttext, TXTBOX_COUNT, aptl ) ;
  1940.             if( widthflag ) {
  1941.                 if( bHorz ) textwidth += aptl[TXTBOX_BOTTOMRIGHT].x ;
  1942.                 else        textwidth += aptl[TXTBOX_BOTTOMRIGHT].y ;
  1943.                 }
  1944.             }
  1945.         if( bText ) {
  1946.             if( textlen > 0 ) {
  1947.                 if( showflag)
  1948.                     GpiCharStringAt( hps, &ptlText, textlen, starttext ) ;
  1949.                 if( widthflag ) {
  1950.                     ptlText.x += aptl[TXTBOX_CONCAT].x ;
  1951.                     ptlText.y += aptl[TXTBOX_CONCAT].y ;
  1952.                     }
  1953.                 }
  1954.             if( base != 0 ) {
  1955.                 ptlText.x -= (bHorz?0:(-base)) ;
  1956.                 ptlText.y -= (bHorz?base:0) ;
  1957.                 }
  1958.             }
  1959.         if( bChangeFont ) {
  1960.             SwapFont( hps, NULL ) ;
  1961.             bChangeFont = FALSE ;
  1962.             }
  1963.     if( base != 0 ) GpiSetCharBox( hps, &sizBaseFont ) ;        
  1964.                 
  1965.  
  1966.         textlen = 0 ;
  1967.         starttext = p+1 ;
  1968.     return p;
  1969.  
  1970. static void CharStringAt(HPS hps, int x, int y, int len, char *str)
  1971. {
  1972.     /* flush any pending graphics (all the XShow routines do this...) */
  1973.  
  1974.      char *fontname ;
  1975.      int fontsize ;
  1976.  
  1977.     if (!strlen(str))
  1978.         return;
  1979.  
  1980.     /* set up the globals */
  1981.     
  1982.         ptlText.x = x ;
  1983.         ptlText.y = y ;
  1984.         bText = TRUE ;
  1985.         starttext = NULL ;
  1986.         textlen = 0 ;
  1987.         textwidth = 0 ;
  1988.         sscanf( szFontNameSize, "%d", &fontsize ) ;
  1989.         fontname = strchr( szFontNameSize, '.' ) + 1 ;
  1990.         
  1991.     while (*(str = ParseText(hps, str, TRUE, NULL,
  1992.                      fontsize,
  1993.                      0.0, TRUE, TRUE)));
  1994.  
  1995. }
  1996.  
  1997. static int QueryTextBox( HPS hps, int len, char *str ) 
  1998. {
  1999.      char *fontname ;
  2000.      int fontsize ;
  2001.     if (!strlen(str))
  2002.         return 0 ;
  2003.  
  2004.  
  2005.     /* set up the globals */
  2006.     
  2007.         bText = FALSE ;
  2008.         starttext = NULL ;
  2009.         textlen = 0 ;
  2010.         textwidth = 0 ;
  2011.         sscanf( szFontNameSize, "%d", &fontsize ) ;
  2012.         fontname = strchr( szFontNameSize, '.' ) + 1 ;
  2013.         
  2014.     while (*(str = ParseText(hps, str, TRUE, NULL,
  2015.                      fontsize,
  2016.                      0.0, TRUE, TRUE)));
  2017.  
  2018.     return textwidth ;    
  2019. }
  2020.  
  2021. void FontExpand( char *name )
  2022.     {
  2023.     if     ( strcmp(name,"S")==0 ) strcpy( name, "Symbol Set" ) ;
  2024.     else if( strcmp(name,"H")==0 ) strcpy( name, "Helvetica" ) ;
  2025.     else if( strcmp(name,"T")==0 ) strcpy( name, "Times New Roman" ) ;
  2026.     else if( strcmp(name,"C")==0 ) strcpy( name, "Courier" ) ;
  2027.     }
  2028.  
  2029. /*=======================================*/
  2030. static POINTL pCur ;
  2031. static int iLinebegin = 1 ;
  2032. static int iLtype = 0 ;
  2033. static int iState = 0 ;
  2034. static double togo = 0.0 ;
  2035. static int iPatt[8][9]
  2036.   = {
  2037.     {   0,   0,   0,   0,   0,   0,   0,   0,  0 },
  2038.     { 300, 200,  -1,   0,   0,   0,   0,   0,  0 },
  2039.     { 150, 150,  -1,   0,   0,   0,   0,   0,  0 },
  2040.     { 300, 200, 150, 200,  -1,   0,   0,   0,  0 },
  2041.     { 500, 200,  -1,   0,   0,   0,   0,   0,  0 },
  2042.     { 300, 200, 150, 200, 150, 200,  -1,   0,  0 },
  2043.     { 300, 200, 150, 200, 150, 200, 150, 200, -1 },
  2044.     { 500, 200, 150, 200,  -1,   0,   0,   0,  0 }
  2045.     } ;
  2046.  
  2047. void LMove( HPS hps, POINTL *p )
  2048.     {
  2049.     double ds, dx, dy ;
  2050.     if( iLinebegin ) {
  2051.         pCur = *p ;
  2052.         GpiMove( hps, p ) ;
  2053.         }
  2054.     else if( iLtype == 0 ) GpiMove( hps, p ) ;
  2055.     else {
  2056.         dx = p->x - pCur.x ;
  2057.         dy = p->y - pCur.y ;
  2058.         ds = sqrt( dx*dx + dy*dy ) ;
  2059.         dx /= ds ; dy /= ds ;
  2060.         while( ds > 0.0 ) {
  2061.             if( ds < togo ) {
  2062.                 togo -= ds ;
  2063.                 ds = 0.0 ;
  2064.                 GpiMove( hps, p ) ;
  2065.                 pCur = *p ;
  2066.                 }
  2067.             else {
  2068.                 POINTL pn ;
  2069.                 pn.x = pCur.x + togo * dx ;
  2070.                 pn.y = pCur.y + togo * dy ;
  2071.                 GpiMove( hps, &pn ) ;
  2072.                 pCur = pn ;
  2073.                 ds -= togo ;
  2074.                 iState++ ;
  2075.                 if( iPatt[iLtype][iState] < 0 ) {
  2076.                     togo = iPatt[iLtype][0] ;
  2077.                     iState = 0 ;
  2078.         }
  2079.                 else togo = iPatt[iLtype][iState] ;
  2080.     }
  2081.             }
  2082.         }
  2083.     } 
  2084.  
  2085. void LLine( HPS hps, POINTL *p )
  2086.     {
  2087.     double ds, dx, dy ;
  2088.     if( iLinebegin ) iLinebegin = 0 ;
  2089.  
  2090.     if( iLtype == 0 ) GpiLine( hps, p ) ;
  2091.     else {
  2092.         dx = p->x - pCur.x ;
  2093.         dy = p->y - pCur.y ;
  2094.         ds = sqrt( dx*dx + dy*dy ) ;
  2095.         dx /= ds ; dy /= ds ;
  2096.         while( ds > 0.0 ) {
  2097.             if( ds < togo ) {
  2098.                 togo -= ds ;
  2099.                 ds = 0.0 ;
  2100.                 if( iState&1 ) GpiMove( hps, p ) ;
  2101.                 else GpiLine( hps, p ) ;
  2102.                 pCur = *p ;
  2103.                 }
  2104.             else {
  2105.                 POINTL pn ;
  2106.                 pn.x = pCur.x + togo * dx ;
  2107.                 pn.y = pCur.y + togo * dy ;
  2108.                 if( iState&1 ) GpiMove( hps, &pn ) ;
  2109.                 else GpiLine( hps, &pn ) ;
  2110.                 pCur = pn ;
  2111.                 ds -= togo ;
  2112.                 iState++ ;
  2113.                 if( iPatt[iLtype][iState] < 0 ) {
  2114.                     togo = iPatt[iLtype][0] ;
  2115.                     iState = 0 ;
  2116.                     }
  2117.                 else togo = iPatt[iLtype][iState] ;
  2118.                 }
  2119.             }
  2120.         }
  2121.     } 
  2122.  
  2123. void LType( int iType )
  2124.     {
  2125.     iLinebegin = 1 ;
  2126.     if( iType > 7 ) iType = 0 ;
  2127.     iLtype = iType ;
  2128.     iState = 0 ;
  2129.     togo = iPatt[iLtype][0] ;
  2130.     }
  2131.  
  2132.